package com.devo.icecream.utils;


import com.serotonin.modbus4j.base.ModbusUtils;

public class ByteUtil {
    public static int isOdd(int num) {
        return num & 0x1;
    }

    public static int HexToInt(String inHex) {
        return Integer.parseInt(inHex, 16);
    }

    public static byte HexToByte(String inHex) {
        return (byte) Integer.parseInt(inHex, 16);
    }

    public static String Byte2Hex(Byte inByte) {
        return String.format("%02x", new Object[]{inByte}).toUpperCase();
    }

    public static String ByteArrToHex(byte[] inBytArr) {
        StringBuilder strBuilder = new StringBuilder();
        int j = inBytArr.length;
        for (int i = 0; i < j; i++) {
            strBuilder.append(Byte2Hex(Byte.valueOf(inBytArr[i])));
            strBuilder.append("");
        }
        return String.join(" ", strBuilder.toString().split(""));
    }

    public static String ByteArrToHex(byte[] inBytArr, int offset, int byteCount) {
        StringBuilder strBuilder = new StringBuilder();
        int j = byteCount;
        for (int i = offset; i < j; i++) {
            strBuilder.append(Byte2Hex(Byte.valueOf(inBytArr[i])));
        }
        return strBuilder.toString();
    }

    public static byte[] HexToByteArr(String inHex) {
        int hexlen = inHex.length();
        byte[] result;
        if (isOdd(hexlen) == 1) {
            hexlen++;
            result = new byte[hexlen / 2];
            inHex = "0" + inHex;
        } else {
            result = new byte[hexlen / 2];
        }
        int j = 0;
        for (int i = 0; i < hexlen; i += 2) {
            result[j] = HexToByte(inHex.substring(i, i + 2));
            j++;
        }
        return result;
    }

    public static String toHexString(byte[] input, String separator) {
        if (input == null) return null;

        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < input.length; i++) {
            if (separator != null && sb.length() > 0) {
                sb.append(separator);
            }
            String str = Integer.toHexString(input[i] & 0xff);
            if (str.length() == 1) str = "0" + str;
            sb.append(str);
        }
        return sb.toString();
    }

    public static String toHexString(byte[] input) {
        return toHexString(input, " ");
    }

    public static byte[] fromInt32(int input) {
        byte[] result = new byte[4];
        result[3] = (byte) (input >> 24 & 0xFF);
        result[2] = (byte) (input >> 16 & 0xFF);
        result[1] = (byte) (input >> 8 & 0xFF);
        result[0] = (byte) (input & 0xFF);
        return result;
    }

    public static byte[] fromInt16(int input) {
        byte[] result = new byte[2];
        result[0] = (byte) (input >> 8 & 0xFF);
        result[1] = (byte) (input & 0xFF);
        return result;
    }

    public static byte[] fromInt16Reversal(int input) {
        byte[] result = new byte[2];
        result[1] = (byte) (input >> 8 & 0xFF);
        result[0] = (byte) (input & 0xFF);
        return result;
    }

    public static byte[] intToByteArray(int i) {
        byte[] result = new byte[4];
        result[0] = (byte) ((i >> 24) & 0xFF);
        result[1] = (byte) ((i >> 16) & 0xFF);
        result[2] = (byte) ((i >> 8) & 0xFF);
        result[3] = (byte) (i & 0xFF);
        return result;
    }

    public static int bytesToIntBySwapped(byte[] bytes) {
        return bytesToInt(swapped(bytes));
    }

    public static byte[] swapped(byte[] bytes) {
        int length = bytes.length;
        byte[] newBytes = new byte[length];
        for (int i = 0; i < length; i += 2) {
            newBytes[length - 2 - i] = bytes[i];
            newBytes[length - 1 - i] = bytes[i + 1];
        }
        return newBytes;
    }

    public static int swapped(int data) {
        return data << 16 | data >> 16;
    }

    public static float swapped(float data) {
        return Float.intBitsToFloat(swapped(Float.floatToIntBits(data)));
    }


    /**
     * <p>convertToShorts.</p>
     *
     * @param data an array of {@link byte} objects.
     * @return an array of {@link short} objects.
     */
    public static short[] convertToShorts(byte[] data) {
        short[] sdata = new short[data.length / 2];
        for (int i = 0; i < sdata.length; i++)
            sdata[i] = ModbusUtils.toShort(data[i * 2], data[i * 2 + 1]);
        return sdata;
    }

    public static byte[] floatToByteArraySwapped(float value) {
        int i = Float.floatToIntBits(value);
        byte[] o = intToByteArray(i);
        return new byte[]{
                o[2], o[3], o[0], o[1]
        };
    }

    public static short[] floatToShortArray(float data) {
        return convertToShorts(floatToByteArraySwapped(data));
    }


    public static short[] intToShortArray(int data) {
        return convertToShorts(swapped(intToByteArray(data)));
    }


    public static int bytesToInt(byte[] bytes) {
        int value = 0;
        for (byte b : bytes) {
            value = (value << 8) + (b & 0xFF);
        }
        return value;
    }

    public static int[] bytesToIntArray(byte[] bytes) {
        int[] arrays = new int[bytes.length];
        for (int i = 0; i < bytes.length; i++) {
            arrays[i] = bytes[i];
        }
        return arrays;
    }
}
